/**
 * Copyright (C)  2011  chen wei hua.
 * Permission is granted to copy, distribute and/or modify this document
 * under the terms of the GNU Free Documentation License, Version 2.0
 * or any later version published by the Free Software Foundation;
 * with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
 * A copy of the license is included in the section entitled "GNU Free Documentation License".
 */
package com.javaeye.accounting.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.javaeye.accounting.dao.MaterialsMonthBatchDetailDAO;
import com.javaeye.accounting.dto.MaterialsMonthBatchDetail;
import com.javaeye.accounting.dto.MaterialsMonthChangeDetail;
import com.javaeye.common.util.DateUtils;
import com.javaeye.common.util.NumberUtils;
import com.javaeye.store.dao.MaterialsBatchDetailDAO;
import com.javaeye.store.dao.MaterialsChangeDetailDAO;
import com.javaeye.store.dto.MaterialsBatchDetail;
import com.javaeye.store.dto.MaterialsChangeDetail;

public class MaterialsMonthChangeDetailService implements IMaterialsMonthChangeDetailService {
	
	private MaterialsMonthBatchDetailDAO materialsMonthBatchDetailDao;
	
	private MaterialsChangeDetailDAO materialsChangeDetailDao;
	
	private MaterialsBatchDetailDAO materialsBatchDetailDao;
	
	public void setMaterialsMonthBatchDetailDao(
			MaterialsMonthBatchDetailDAO materialsMonthBatchDetailDao) {
		this.materialsMonthBatchDetailDao = materialsMonthBatchDetailDao;
	}

	public void setMaterialsChangeDetailDao(
			MaterialsChangeDetailDAO materialsChangeDetailDao) {
		this.materialsChangeDetailDao = materialsChangeDetailDao;
	}

	public void setMaterialsBatchDetailDao(
			MaterialsBatchDetailDAO materialsBatchDetailDao) {
		this.materialsBatchDetailDao = materialsBatchDetailDao;
	}
	
	private MaterialsMonthChangeDetail initMaterialsMonthChangeDetail(
			Date recordDate, String voucherNo, String name, String batchNo, double price) {
		MaterialsMonthChangeDetail detail = new MaterialsMonthChangeDetail();
		detail.setDate(recordDate);
		detail.setVoucherNo(voucherNo);
		detail.setName(name);
		detail.setBatchNo(batchNo);
		detail.setPrice(price);
		return detail;
	}
	
	
	/**
	 * 生成不合格台帐明细
	 */
	@Override
	public List<MaterialsMonthChangeDetail> queryMaterialsDefectiveMonthChangeDetail(
			String monthNo, int skuId) {
		
		List<MaterialsMonthChangeDetail> details = new ArrayList<MaterialsMonthChangeDetail>();
		
		//统计上期不合格库存
		String beforeMonthNo = DateUtils.getBeforeMonthNo(monthNo);
		List<MaterialsMonthBatchDetail> beforeMonthDetail = 
			materialsMonthBatchDetailDao.getMonthInfo(beforeMonthNo, skuId);
		double totleAmount = 0;
		float totleCount = 0;
		for (MaterialsMonthBatchDetail detail : beforeMonthDetail) {
			
			float number = detail.getDefectiveNumber();
			if (number > 0) {
				totleCount += number;
				double price = detail.getPrice();
				totleAmount += number * price;
			}
		}
		MaterialsMonthChangeDetail detail = new MaterialsMonthChangeDetail();
		detail.setName("上期结存");
		detail.setNumber(totleCount);
		detail.setAmount(NumberUtils.formatDouble(totleAmount));
		details.add(detail);
		
		//取得本期明细
		List<MaterialsChangeDetail> changeDetails = 
			materialsChangeDetailDao.getMaterialsChangeInfo(
					DateUtils.getMonthNoBeginDate(monthNo),
					DateUtils.getMonthNoEndDate(monthNo), skuId);
		for (MaterialsChangeDetail changeDetail : changeDetails) {
			
			String batchNo = changeDetail.getBatchNo();
			MaterialsBatchDetail batchDetail = 
				materialsBatchDetailDao.getBatchDetail(skuId, batchNo);
			double price = batchDetail.getPrice();
			
			int changeType = changeDetail.getChangeType();
			switch (changeType) {
			case MaterialsChangeDetail.PROCUREMENT_UNQUALIFIED_INSTORE:
				detail = initMaterialsMonthChangeDetail(
						changeDetail.getRecordDate(),
						changeDetail.getVoucherNo(),
						"采购收货不合格入库",
						batchNo,
						price
				);
				float number = changeDetail.getNumber();
				detail.setInNumber(number);
				
				totleCount += number;
				detail.setNumber(totleCount);
				
				totleAmount += number * price;
				detail.setAmount(NumberUtils.formatDouble(totleAmount));
				details.add(detail);
				break;
			case MaterialsChangeDetail.MATERIALS_UNQUALIFIED_INSTORE:
				detail = initMaterialsMonthChangeDetail(
						changeDetail.getRecordDate(),
						changeDetail.getVoucherNo(),
						"车间不合格退货入库",
						batchNo,
						price
				);
				number = changeDetail.getNumber();
				detail.setInNumber(number);
				
				totleCount += number;
				detail.setNumber(totleCount);
				
				totleAmount += number * price;
				detail.setAmount(NumberUtils.formatDouble(totleAmount));
				details.add(detail);
				break;
			case MaterialsChangeDetail.ADJUST_INVENTORY_UNQUALIFIED_IN_STORE:
				detail = initMaterialsMonthChangeDetail(
						changeDetail.getRecordDate(),
						changeDetail.getVoucherNo(),
						"盘点调帐不合格品入库",
						batchNo,
						price
				);
				number = changeDetail.getNumber();
				detail.setInNumber(number);
				
				totleCount += number;
				detail.setNumber(totleCount);
				
				totleAmount += number * price;
				detail.setAmount(NumberUtils.formatDouble(totleAmount));
				details.add(detail);
				break;
			case MaterialsChangeDetail.PROCUREMENT_UNQUALIFIED_OUTSTORE:
				detail = initMaterialsMonthChangeDetail(
						changeDetail.getRecordDate(),
						changeDetail.getVoucherNo(),
						"采购不合格品退货出库",
						batchNo,
						price
				);
				number = changeDetail.getNumber();
				detail.setOutNumber(number);
				
				totleCount -= number;
				detail.setNumber(totleCount);
				
				totleAmount -= number * price;
				detail.setAmount(NumberUtils.formatDouble(totleAmount));
				details.add(detail);
				break;
			case MaterialsChangeDetail.ADJUST_INVENTORY_UNQUALIFIED_OUT_STORE:
				detail = initMaterialsMonthChangeDetail(
						changeDetail.getRecordDate(),
						changeDetail.getVoucherNo(),
						"盘点调帐不合格品出库",
						batchNo,
						price
				);
				number = changeDetail.getNumber();
				detail.setOutNumber(number);
				
				totleCount -= number;
				detail.setNumber(totleCount);
				
				totleAmount -= number * price;
				detail.setAmount(NumberUtils.formatDouble(totleAmount));
				details.add(detail);
				break;
			default:
				break;
			}
		}
		
		//统计本期结余
		detail = new MaterialsMonthChangeDetail();
		detail.setName("本期结余");
		detail.setNumber(totleCount);
		detail.setAmount(NumberUtils.formatDouble(totleAmount));
		details.add(detail);
		
		return details;
	}
	
	/**
	 * 生成合格台帐明细
	 */
	@Override
	public List<MaterialsMonthChangeDetail> queryMaterialsMonthChangeDetail(
			String monthNo, int skuId) {
		
		List<MaterialsMonthChangeDetail> details = new ArrayList<MaterialsMonthChangeDetail>();
		
		//统计上期合格库存
		String beforeMonthNo = DateUtils.getBeforeMonthNo(monthNo);
		List<MaterialsMonthBatchDetail> beforeMonthDetail = 
			materialsMonthBatchDetailDao.getMonthInfo(beforeMonthNo, skuId);
		double totleAmount = 0;
		float totleCount = 0;
		for (MaterialsMonthBatchDetail detail : beforeMonthDetail) {
			
			float number = detail.getNumber();
			if (number > 0) {
				totleCount += number;
				double price = detail.getPrice();
				totleAmount += number * price;
			}
		}
		MaterialsMonthChangeDetail detail = new MaterialsMonthChangeDetail();
		detail.setName("上期结存");
		detail.setNumber(totleCount);
		detail.setAmount(NumberUtils.formatDouble(totleAmount));
		details.add(detail);
		
		//取得本期明细
		List<MaterialsChangeDetail> changeDetails = 
			materialsChangeDetailDao.getMaterialsChangeInfo(
					DateUtils.getMonthNoBeginDate(monthNo),
					DateUtils.getMonthNoEndDate(monthNo), skuId);
		for (MaterialsChangeDetail changeDetail : changeDetails) {
			
			String batchNo = changeDetail.getBatchNo();
			MaterialsBatchDetail batchDetail = 
				materialsBatchDetailDao.getBatchDetail(skuId, batchNo);
			double price = batchDetail.getPrice();
			
			int changeType = changeDetail.getChangeType();
			switch (changeType) {
			case MaterialsChangeDetail.PLAN_INSTORE:
				detail = initMaterialsMonthChangeDetail(
						changeDetail.getRecordDate(),
						changeDetail.getVoucherNo(),
						"订单成品入库",
						batchNo,
						price
				);
				float number = changeDetail.getNumber();
				detail.setInNumber(number);
				
				totleCount += number;
				detail.setNumber(totleCount);
				
				totleAmount += number * price;
				detail.setAmount(NumberUtils.formatDouble(totleAmount));
				details.add(detail);
				break;
			case MaterialsChangeDetail.PROCUREMENT_QUALIFIED_INSTORE:
				detail = initMaterialsMonthChangeDetail(
						changeDetail.getRecordDate(),
						changeDetail.getVoucherNo(),
						"采购收货合格入库",
						batchNo,
						price
				);
				number = changeDetail.getNumber();
				detail.setInNumber(number);
				
				totleCount += number;
				detail.setNumber(totleCount);
				
				totleAmount += number * price;
				detail.setAmount(NumberUtils.formatDouble(totleAmount));
				details.add(detail);
				break;
			case MaterialsChangeDetail.MATERIALS_QUALIFIED_INSTORE:
				detail = initMaterialsMonthChangeDetail(
						changeDetail.getRecordDate(),
						changeDetail.getVoucherNo(),
						"车间合格退货入库",
						batchNo,
						price
				);
				number = changeDetail.getNumber();
				detail.setInNumber(number);
				
				totleCount += number;
				detail.setNumber(totleCount);
				
				totleAmount += number * price;
				detail.setAmount(NumberUtils.formatDouble(totleAmount));
				details.add(detail);
				break;
			case MaterialsChangeDetail.ADJUST_INVENTORY_QUALIFIED_IN_STORE:
				detail = initMaterialsMonthChangeDetail(
						changeDetail.getRecordDate(),
						changeDetail.getVoucherNo(),
						"盘点调帐合格品入库",
						batchNo,
						price
				);
				number = changeDetail.getNumber();
				detail.setInNumber(number);
				
				totleCount += number;
				detail.setNumber(totleCount);
				
				totleAmount += number * price;
				detail.setAmount(NumberUtils.formatDouble(totleAmount));
				details.add(detail);
				break;
			case MaterialsChangeDetail.PRODUCT_OUTSTORE:
				detail = initMaterialsMonthChangeDetail(
						changeDetail.getRecordDate(),
						changeDetail.getVoucherNo(),
						"订单成品出库",
						batchNo,
						price
				);
				number = changeDetail.getNumber();
				detail.setOutNumber(number);
				
				totleCount -= number;
				detail.setNumber(totleCount);
				
				totleAmount -= number * price;
				detail.setAmount(NumberUtils.formatDouble(totleAmount));
				details.add(detail);
				break;
			case MaterialsChangeDetail.MATERIALS_OUTSTORE:
				detail = initMaterialsMonthChangeDetail(
						changeDetail.getRecordDate(),
						changeDetail.getVoucherNo(),
						"车间领用出库",
						batchNo,
						price
				);
				number = changeDetail.getNumber();
				detail.setOutNumber(number);
				
				totleCount -= number;
				detail.setNumber(totleCount);
				
				totleAmount -= number * price;
				detail.setAmount(NumberUtils.formatDouble(totleAmount));
				details.add(detail);
				break;
			case MaterialsChangeDetail.ADJUST_INVENTORY_QUALIFIED_OUT_STORE:
				detail = initMaterialsMonthChangeDetail(
						changeDetail.getRecordDate(),
						changeDetail.getVoucherNo(),
						"盘点调帐合格品出库",
						batchNo,
						price
				);
				number = changeDetail.getNumber();
				detail.setOutNumber(number);
				
				totleCount -= number;
				detail.setNumber(totleCount);
				
				totleAmount -= number * price;
				detail.setAmount(NumberUtils.formatDouble(totleAmount));
				details.add(detail);
				break;
			default:
				break;
			}
		}
		
		//统计本期结余
		detail = new MaterialsMonthChangeDetail();
		detail.setName("本期结余");
		detail.setNumber(totleCount);
		detail.setAmount(NumberUtils.formatDouble(totleAmount));
		details.add(detail);
		
		return details;
	}

}
